#ifndef POINT_H
#define POINT_H


#include <iostream>
#include <vector>
#include <algorithm>
#include <initializer_list>
#include <math.h>
#include <assert.h>


/**
 * @brief 几何点类，生成指定维度的几何点；
 */
template<unsigned int DIM>
class Point
{
public:
    /**
     * @brief 生成一个各个分量均为0的DIM维的点；
     */
    Point();

    /**
     * @brief Construct a new Point object by initializer_list in std namespace;
     *        生成一个指定维度几何点，各个分量与initializer_list各分量相同的几何点；
     * @param Point_list stl库中的initializer_list,语法为：Point<2> p = {0,0};
     */
    Point(const std::initializer_list<double> Point_list);

    /**
     * @brief    生成一个指定维度几何点，各个分量与vector各分量相同的几何点；
     * @param Point_vector stl库中的vector
     */
    Point(const std::vector<double> Point_vector);
    /**
     * @brief 重载下标运算符operator[]，可以用p[0]表示已经声明的几何点的第一个维度；
     * 
     * @param d 指定维度；
     * @return double& 返回一个实数类型的应用。
     */
    double& operator[](const unsigned int d);
    /** 
     * 返回点的坐标值数组
     * 
     * 
     * @return _value
     */
    double* get_value();
     /**
     * @brief Destroy the Point object
     */
    ~Point();
protected:
    double _value[DIM];
};

template<unsigned int DIM>
Point<DIM>::Point()
{
    std::fill(_value, _value + DIM, static_cast<double>(0));
};

template<unsigned int DIM>
Point<DIM>::Point(const std::initializer_list<double> Point_list)
{
    if(Point_list.size() != DIM)
    {
	std::cerr << "Point::DIM not same." <<std::endl;
    }
    std::initializer_list<double>::const_iterator i_begin = Point_list.begin();
    std::initializer_list<double>::const_iterator i_end = Point_list.end();
    std::copy(i_begin, i_end,_value);
};
template<unsigned int DIM>
Point<DIM>::Point(const std::vector<double> Point_vector)
{
    if(Point_vector.size() != DIM)
    {
	std::cerr << "Point::DIM not same." <<std::endl;
    }
    std::vector<double>::const_iterator i_begin = Point_vector.begin();
    std::vector<double>::const_iterator i_end = Point_vector.end();
    std::copy(i_begin, i_end, _value);
};



template<unsigned int DIM>
Point<DIM>::~Point()
{
}

template<unsigned int DIM>
double& Point<DIM>::operator[](const unsigned int d)
{
    return _value[d];
}
template <unsigned int DIM>
double* Point<DIM>::get_value()
{
    return _value;
};



template<unsigned int DIM>
class Boundary
{
public:
    Boundary() = default;
    Boundary(std::vector<Point<DIM>> temp);
    bool is_on_boundary(Point<DIM> point);
    void setsegment(std::vector<Point<2>> temp);
    const std::vector<Point<DIM> >& getsegment() const;
private:
    std::vector<Point<DIM> > _segmentpointlist;
};

template <unsigned int DIM>
Boundary<DIM>::Boundary(std::vector<Point<DIM>> temp)
{
  _segmentpointlist = temp;
};

template<unsigned int DIM>
bool Boundary<DIM>::is_on_boundary(Point<DIM> point)
{
    assert(DIM==2);
    double x1 = _segmentpointlist[0][0];
    double y1 = _segmentpointlist[0][1];
    double x2 = _segmentpointlist[1][0];
    double y2 = _segmentpointlist[1][1];
    double x = point[0];
    double y = point[1];
    if(x1 > x2)//按照x从小到大
    {
	std::swap(x1,x2);
        std::swap(y1,y2);
    }
    bool ans = false;
    // if(y1 == y2)
    // {
    //     if(x >= x1 && x <= x2)
    //         ans = (y == y1);    
    // }
    // else if(x1 == x2)
    // {
    //     if(y2 > y1)
    //     {
    //         ans = ((x == x1) &&( y >= y1 && y <= y2));
    //     }
    //     else
    //     {
    //         ans = ((x == x1) &&( y >= y2 && y <= y1 ));
    //     }      
    // }
    if((y1 - y2)*x + (x2 - x1)*y - y1*x2 + x1*y2 == 0)
    {
	ans = true;
    }
    return ans;
};

template<unsigned int DIM>
void Boundary<DIM>::setsegment(std::vector<Point<2>> temp)
{
    _segmentpointlist = temp;
};

template<unsigned int DIM>
const std::vector<Point<DIM> >& Boundary<DIM>::getsegment() const
{
    return _segmentpointlist;
};


#endif /* POINT_H */
